home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / mpp.exe / CGC.CPP < prev    next >
C/C++ Source or Header  |  1992-10-07  |  8KB  |  246 lines

  1. /* -------------------------------------------------------------------- */
  2. /* Mouse++ Version 4.0            cgc.cpp              Revised 10/05/92 */
  3. /*                                                                      */
  4. /* General mouse class for Turbo C++/Borland C++.                       */
  5. /* Copyright 1991, 1992 by Carl W. Moreland                             */
  6. /* -------------------------------------------------------------------- */
  7. /* This module contains the ColorGraphicsCursor routines for displaying */
  8. /* the color images. It is written entirely in C++ (no assembly) to de- */
  9. /* monstrate exactly how the image is written to video memory and how   */
  10. /* the cursor is masked at the screen edges.                            */
  11. /* -------------------------------------------------------------------- */
  12.  
  13. #include <dos.h>
  14. #include <mem.h>
  15. #include "mouse.h"
  16.  
  17. const int screenWidth  = 640;        // VGA/EGA = 640
  18. const int screenHeight = 350;           // VGA = 480, EGA = 350
  19.  
  20. int            ColorGraphicsCursor::x = -1;
  21. int            ColorGraphicsCursor::y = -1;
  22. void*          ColorGraphicsCursor::tmpImage = NULL;
  23. int            ColorGraphicsCursor::tmpImageSize = 0;
  24. unsigned char* ColorGraphicsCursor::videoAddress;
  25. int            ColorGraphicsCursor::videoLeftMask;
  26. int            ColorGraphicsCursor::videoRightMask;
  27. int            ColorGraphicsCursor::screenLeftMask;
  28. int            ColorGraphicsCursor::screenRightMask;
  29. unsigned char  ColorGraphicsCursor::xStart;
  30. unsigned char  ColorGraphicsCursor::yStart;
  31. unsigned char  ColorGraphicsCursor::xEnd;
  32. unsigned char  ColorGraphicsCursor::yEnd;
  33. unsigned char  ColorGraphicsCursor::iWidth;
  34. unsigned char  ColorGraphicsCursor::iHeight;
  35.  
  36.  
  37. ColorGraphicsCursor::ColorGraphicsCursor(unsigned char hotx,
  38.                                          unsigned char hoty,
  39.                                          unsigned char image[],
  40.                                          unsigned char width,
  41.                                          unsigned char height)
  42. {
  43.   this->hotx = hotx;
  44.   this->hoty = hoty;
  45.   cWidth     = width;
  46.   cHeight    = height;
  47.   cBytes     = width/8 + (width%8 ? 1 : 0);
  48.  
  49.   int nBytes = cHeight * cBytes;    // total # of bytes in each plane
  50.  
  51.   cMask  = (void *)image;        // screen mask is the first plane
  52.   cImage = (void *)(image + nBytes);    // cursor starts with second plane
  53.  
  54.   for(int i = 0; i < nBytes; i++)    // invert the screen mask
  55.     image[i] = ~image[i];
  56.  
  57.   if(5*nBytes > tmpImageSize)        // resize the tmp buffer if
  58.   {                    //  necessary
  59.     if(tmpImage)
  60.       delete tmpImage;
  61.     tmpImage = new unsigned char[5*nBytes];
  62.     tmpImageSize = 5*nBytes;
  63.   }
  64. }
  65.  
  66. void ColorGraphicsCursor::VideoRead(void)
  67. {
  68.   static unsigned char *image, *address;
  69.   static int new_x, new_y;
  70.   register int i, j, k;
  71.  
  72.   xStart = 0;
  73.   xEnd   = cBytes;
  74.   yStart = 0;
  75.   yEnd   = cHeight;
  76.   new_x  = x - hotx;            // left edge of the image
  77.   new_y  = y - hoty;            // top edge of the image
  78.  
  79.   videoLeftMask  = 0xFF >> (new_x&7);
  80.   videoRightMask = ~videoLeftMask;
  81.  
  82.   if(new_x < 0)                // if the left edge < 0
  83.   {
  84.     xStart = -(new_x>>3);        // shift xStart n bytes
  85.     new_x  = 0;
  86.   }                                     // if the right edge > screenWidth-1
  87.   else if(new_x+(cBytes<<3) > screenWidth-1)
  88.     xEnd = (screenWidth-new_x-1)>>3;    // shift xEnd n bytes
  89.  
  90.   if(new_y < 0)                // if the top edge < 0
  91.   {
  92.     yStart = -new_y+1;            // shift yStart n rows
  93.     new_y  = 0;
  94.   }                                     // if the bottom edge>screenHeight-1
  95.   else if(new_y+cHeight > screenHeight-1)
  96.     yEnd = screenHeight-new_y;        // shift yEnd n rows
  97.  
  98.   iWidth  = xEnd - xStart;        // width in bytes
  99.   iHeight = yEnd - yStart;        // height in bytes
  100.  
  101.   videoAddress = (unsigned char*)MK_FP(0xA000, (new_y*80 + (new_x>>3)));
  102.  
  103.   image = (unsigned char *)tmpImage;
  104.  
  105.   outp(0x3CE, 5);            // select read mode 0
  106.   outp(0x3CF, 0);
  107.  
  108.   for(i = 0; i < 4; i++)        // for each bitplane...
  109.   {
  110.     address = videoAddress;
  111.     outp(0x3CE, 4);            // select the bit plane...
  112.     outp(0x3CF, i);
  113.  
  114.     for(j = yStart; j < yEnd; j++)    // for each cursor line...
  115.     {
  116.       for(k = xStart; k <= xEnd; k++)    // for each byte...
  117.       {
  118.         *image = *address;        // save the byte
  119.         image++;
  120.         address++;
  121.       }
  122.       address += 79-iWidth;        // go to the next line
  123.     }
  124.   }
  125. }
  126.  
  127. void ColorGraphicsCursor::VideoWrite(void)
  128. {
  129.   static unsigned char *image, *address, vByte=0;
  130.   register int i, j, k;
  131.  
  132.   image = (unsigned char *)tmpImage;
  133.  
  134.   outp(0x3CE, 5);            // select write mode 0
  135.   outp(0x3CF, 0);
  136.   outp(0x3CE, 3);
  137.   outp(0x3CF, 0);
  138.  
  139.   for(i=0; i<4; i++)            // for each bitplane...
  140.   {
  141.     address = videoAddress;
  142.     outp(0x3C4, 2);            // select the bit plane...
  143.     outp(0x3C5, 1<<i);
  144.     outp(0x3CE, 8);
  145.  
  146.     for(j = yStart; j < yEnd; j++)    // for each cursor line...
  147.     {
  148.       for(k = xStart; k <= xEnd; k++)    // for each byte...
  149.       {
  150.         vByte = *address;
  151.  
  152.         if(k == 0)
  153.         {
  154.           outp(0x3CF, videoLeftMask);    // mask off the left byte
  155.         }
  156.         else if(k == cBytes)
  157.         {
  158.           outp(0x3CF, videoRightMask);    // mask off the right byte
  159.         }
  160.         else
  161.         {
  162.           outp(0x3CF, 0xFF);        // middle bytes don't need masking
  163.         }
  164.  
  165.         *address = *image;        // write the byte
  166.         image++;
  167.         address++;
  168.       }
  169.       address += 79-iWidth;        // next cursor line
  170.     }
  171.   }
  172.   outp(0x3CF, 0xFF);
  173. }
  174.  
  175. void ColorGraphicsCursor::CursorWrite(void)
  176. {
  177.   static unsigned char *image, *address, *base, *base0;
  178.   static unsigned char vByte, mask, rShift, lShift;
  179.   register int k, j, i;
  180.  
  181.   image = (unsigned char *)cImage;    // set image to the start of the
  182.  
  183.   base0 = (unsigned char *)cMask;    // base0 is the screen mask
  184.   for(k=0; k<cBytes; k++)        // clip any part that's < yStart
  185.     base0 += yStart;
  186.  
  187.   rShift = (x-hotx)&7;
  188.   lShift = 8-((x-hotx)&7);
  189.  
  190.   outp(0x3CE, 5);            // select write mode 0
  191.   outp(0x3CF, 0);
  192.   outp(0x3CE, 3);
  193.   outp(0x3CF, 0);
  194.  
  195.   for(i=0; i<4; i++)            // for each bit plane...
  196.   {
  197.     address = videoAddress;
  198.     outp(0x3C4, 2);            // select the bit plane...
  199.     outp(0x3C5, 1<<i);
  200.     outp(0x3CE, 8);
  201.  
  202.     for(j=0; j<cBytes; j++)        // clip any part that's < yStart
  203.       image += yStart;
  204.     base = base0;
  205.  
  206.     for(j = yStart; j < yEnd; j++)    // for each cursor line...
  207.     {
  208.       image += xStart;
  209.       base  += xStart;
  210.  
  211.       for(k = xStart; k <= xEnd; k++)    // for each byte...
  212.       {
  213.         vByte = *address;
  214.  
  215.         if(k == 0)
  216.         {
  217.           mask  = *base  >> rShift;    // get the shift mask
  218.           vByte = *image >> rShift;    // shift the image byte
  219.         }
  220.         else if(k == cBytes)
  221.         {
  222.           mask  = *(base-1)  << lShift;
  223.           vByte = *(image-1) << lShift;
  224.         }
  225.         else
  226.         {
  227.           mask  =  (*(base-1) << lShift) |  (*base >> rShift);
  228.           vByte = (*(image-1) << lShift) | (*image >> rShift);
  229.         }
  230.  
  231.         outp(0x3CF, mask);        // mask off the bits
  232.         *address = vByte;        // write the byte to video
  233.         address++;            // next video byte
  234.         image++;            // next image byte
  235.         base++;                // next mask byte
  236.       }
  237.       address += 79-iWidth;        // next cursor line
  238.       image += cBytes-xEnd-1;        // next image line
  239.       base  += cBytes-xEnd-1;        // next mask line
  240.     }
  241.     for(j=0; j<cBytes; j++)        // next bit plane in image
  242.       image += cHeight-yEnd;
  243.   }
  244.   outp(0x3CF, 0xFF);
  245. }
  246.